package com.ytkj.digitalConstruction.service.assets;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ytkj.digitalConstruction.dao.assets.VehicleMapper;
import com.ytkj.digitalConstruction.entity.assets.Device;
import com.ytkj.digitalConstruction.entity.assets.Vehicle;
import com.ytkj.digitalConstruction.httpbean.PageParam;
import com.ytkj.digitalConstruction.httpbean.assets.resbean.ResVehicle;
import com.ytkj.digitalConstruction.httpbean.project.ResProject;
import com.ytkj.digitalConstruction.service.ICommons;
import com.ytkj.digitalConstruction.service.project.ProjectService;
import com.ytkj.digitalConstruction.util.DateUtil;

/**
 * Vehicle表业务层实现
 * 
 * @author
 * @date 2017年12月1日 下午4:16:38
 * @return
 */
@Service
public class VehicleService {

	@Autowired
	private VehicleMapper vehicleMapper;

	@Autowired
	private DeviceService deviceService;

	@Resource
	private HashOperations<String, String, Object> hashOps;

	@Autowired
	private ProjectService projectService;

	/**
	 * 增加车辆
	 * 
	 * @param Vehicler
	 * @param request
	 * @return
	 */
	public boolean insert(Vehicle vehicle) {
		vehicle.setStatus(IAssets.USABLE);
		return vehicleMapper.insertSelective(vehicle) > 0;
	}

	/**
	 * 查询车辆
	 * 
	 * @param id
	 * @param request
	 * @return
	 */
	public Vehicle select(Integer id) {
		return vehicleMapper.selectByPrimaryKey(id);
	}

	/**
	 * 逻辑删除车辆 删除车辆
	 * 
	 * @param id
	 * @param request
	 * @return
	 */
	public Integer delete(Integer id) {
		return vehicleMapper.deleteByIdPrimaryKey(id);
	}

	/**
	 * 修改车辆
	 * 
	 * @param vehicle
	 * @param request
	 * @return
	 */
	public Integer update(Vehicle vehicle) {
		return vehicleMapper.updateByPrimaryKeySelective(vehicle);
	}

	/**
	 * 车牌是否存在
	 * 
	 * @param plateNumber
	 * @param vehicleId
	 * @return
	 */
	public boolean plateNameExists(String plateNumber, Integer vehicleId) {
		Vehicle vehicle = vehicleMapper.selectByPlateNumberPrimaryKey(plateNumber);
		// 数据库中车牌为空，车牌不存在
		if (vehicle == null) {
			return false;
		}
		// 车辆id为空，数据库中不为空，车牌存在
		if (vehicleId == null) {
			return true;
		}
		// 数据库中有车牌，车辆id不为空，
		return vehicleId.intValue() != vehicle.getVehicleId();
	}

	/**
	 * 车辆是否存在
	 * 
	 * @param vehicle
	 * @return
	 */
	public boolean vehicleExists(Vehicle vehicle) {
		return vehicleMapper.selectByPrimaryKey(vehicle.getVehicleId()) != null;
	}

	/**
	 * 根据id查找车辆
	 * 
	 * @param plateId
	 * @return
	 */
	public Vehicle selectByVehicleIdPrimaryKey(Integer vehicleId) {
		return vehicleMapper.selectByPrimaryKey(vehicleId);
	}

	/**
	 * 分页查找用户所有车辆
	 * 
	 * @param id
	 * @param request
	 * @return
	 */
	public Page<ResVehicle> selectAllPageable(int userId, PageParam pageParam) {
		List<Integer> projectIds = new ArrayList<>();
		List<ResProject> projects = projectService.getProjects(userId);
		for (ResProject project : projects) {
			projectIds.add(project.getProjectId());
		}
		PageHelper.startPage(pageParam.getPageCurrent(), pageParam.getPageSize());
		Page<ResVehicle> page = new Page<>();
		if (projectIds.size() > 0) {
			List<ResVehicle> vehicles = findCodeAndLocation(vehicleMapper.selectAllPageable(projectIds));
			page.addAll(vehicles);
			page.setPageSize(pageParam.getPageSize());
			page.setStartRow(pageParam.getPageCurrent());
		}
		return page;
	}

	/**
	 * 根据项目获取车辆
	 * 
	 * @param projectId
	 * @return
	 */
	public List<ResVehicle> selectAllByProject(int projectId) {
		List<ResVehicle> resVehicles = vehicleMapper.selectByProject(projectId);
		return findCodeAndLocation(resVehicles);
	}

	private List<ResVehicle> findCodeAndLocation(List<ResVehicle> vehicles) {
		ResVehicle vehicle = null;
		for (int i = 0; i < vehicles.size(); i++) {
			vehicle = vehicles.get(i);
			vehicle = findCodeAndLocation(vehicle);
		}
		return vehicles;
	}

	/**
	 * 查找车辆实时位置
	 * 
	 * @param vehicleId
	 * @return
	 */
	public JSONObject findRealtimeById(int vehicleId) {
		ResVehicle vehicle = findVehicleById(vehicleId);
		if (vehicle == null) {
			return null;
		}
		Object object = hashOps.get(ICommons.REDIS_KEY_GPS_HISTORY + vehicle.getDeviceExternalCode(),
				DateUtil.dateToString(new Date()));
		return objectToGPSHistory(object);
	}

	/**
	 * 根据车辆id查找一段时间内的车辆轨迹
	 * 
	 * @param vehicleId
	 * @param start
	 * @param end
	 * @return
	 */
	public List<JSONObject> findHistoryById(int vehicleId, Date start, Date end) {
		ResVehicle vehicle = findVehicleById(vehicleId);
		if (vehicle == null) {
			return Collections.emptyList();
		}
		List<String> sortedSecs = new ArrayList<>();
		for (Date date = start; date.before(end); date = DateUtil.increaseBySec(date)) {
			sortedSecs.add(DateUtil.dateToString(date));
		}
		List<Object> objects = hashOps.multiGet(ICommons.REDIS_KEY_GPS_HISTORY + vehicle.getDeviceExternalCode(),
				sortedSecs);
		return listToGPSHistory(filterNullValue(objects));
	}

	/**
	 * 过滤空值
	 * 
	 * @param objects
	 * @return
	 */
	private List<Object> filterNullValue(List<Object> objects) {
		Iterator<Object> its = objects.iterator();
		while (its.hasNext()) {
			Object object = its.next();
			if (object == null) {
				its.remove();
			}
		}
		return objects;
	}

	/**
	 * 根据车辆id获取车辆信息
	 * 
	 * @param vehicleId
	 * @return
	 */
	private ResVehicle findVehicleById(int vehicleId) {
		ResVehicle resVehicle = vehicleMapper.selectByVehicleId(vehicleId);
		if (resVehicle == null) {
			return null;
		}
		return findCodeAndLocation(resVehicle);
	}

	/**
	 * 查找设备外部编码和位置
	 * 
	 * @param vehicle
	 * @return
	 */
	private ResVehicle findCodeAndLocation(ResVehicle vehicle) {
		int bindDevice = vehicle.getBindDevice();
		Device device = deviceService.selectByDeviceIdPrimaryKey(bindDevice);
		if (device == null) {
			return vehicle;
		}
		vehicle.setBindDeviceName(device.getDeviceName());
		String externalCode = device.getExternalCode();
		if (externalCode == null) {
			return vehicle;
		}
		vehicle.setDeviceExternalCode(externalCode);
		Object object = hashOps.get(ICommons.REDIS_KEY_GPS_REALTIME + externalCode, DateUtil.dateToString(new Date()));
		if (object == null) {
			return vehicle;
		}
		JSONObject history = objectToGPSHistory(object);
		vehicle.setLatitude(history.getString("y"));
		vehicle.setLongitude(history.getString("x"));
		return vehicle;
	}

	/**
	 * 将JSON对象集合转换成GPS历史数据对象
	 * 
	 * @param list
	 * @return
	 */
	private List<JSONObject> listToGPSHistory(List<Object> list) {
		List<JSONObject> histories = new ArrayList<>();
		for (Iterator<Object> its = list.iterator(); its.hasNext();) {
			JSONObject history = objectToGPSHistory(its.next());
			if (history == null) {
				its.remove();
				continue;
			}
			histories.add(history);
		}
		return histories;
	}

	/**
	 * 将JSON对象集合转换成GPS历史数据对象
	 * 
	 * @param object
	 * @return
	 */
	private JSONObject objectToGPSHistory(Object object) {
		if (object == null) {
			return null;
		}
		String jsonString = JSONObject.toJSONString(object);
		return JSONObject.parseObject(jsonString);
	}

	/**
	 * 检查设备是否可以使用
	 * 
	 * @param deviceId
	 * @param vehicleId
	 * @return
	 */
	public boolean checkDeviceAndBind(Integer deviceId, Integer vehicleId) {
		List<ResVehicle> vehicles = vehicleMapper.selectByBindDevice(deviceId);
		if (vehicles.isEmpty()) {
			return bindDevice(deviceId);
		}
		return false;
	}

	/**
	 * 绑定设备是否正在使用
	 * 
	 * @param bindDevice
	 * @param vehicleId
	 * @return
	 */
	public boolean bindDevice(Integer bindDevice) {
		Device device = deviceService.selectByDeviceIdPrimaryKey(bindDevice);
		device.setStatus(IAssets.USING);
		return deviceService.update(device);
	}

	/**
	 * 解绑设备
	 * 
	 * @param deviceId
	 * @return
	 */
	public boolean unbindDevice(int deviceId) {
		Device device = deviceService.selectByDeviceIdPrimaryKey(deviceId);
		device.setStatus(IAssets.USABLE);
		return deviceService.update(device);
	}

}
